package cn.biplam.front.template.control.table;

import java.util.ArrayList;
import java.util.Map;

import cn.biplam.common.client.OperatorResult;
import cn.biplam.common.client.Paging;
import cn.biplam.common.wrapper.ErrorMessage;
import cn.biplam.common.wrapper.KvMap;
import cn.biplam.common.wrapper.Result;
import cn.biplam.common.wrapper.UserInfo;
import cn.biplam.front.callback.CallBack;
import cn.biplam.front.component.data.common.PagingComp;
import cn.biplam.front.html.HtmlDiv;
import cn.biplam.front.html.base.HtmlWindow;
import cn.biplam.front.html.base.Const.Window_Event;
import cn.biplam.front.template.base.HiddenParams;
import cn.biplam.front.template.control.rfFlowTable.callback.action.ActionCallback;
import cn.biplam.front.template.control.table.cell.Cell;
import cn.biplam.front.template.control.table.cell.EmptyCell;
import cn.biplam.front.template.control.table.cell.sum.DimensionCell;

/**
 *  含维度的统计表格(清单 OR 统计表格)<BR>
 *  使用方法:<BR>
 *   1.设置分页信息
 *     setPageProperty(跳转动作ID,记录ID)方法 设置表格分页参数(要刷新的目标区域ID就是当前表格)
 *     putPageAddParam(参数名,参数值)方法 设置放入分页所需附加参数
 *   2.设置需要剔重列
 *     setRemoveRepeatCol(列名称)
 * @author XiaoRuxing Dec 1, 20098:29:49 PM
 * @version 1.0
 */
public abstract class DimTable {

//	/****************************
//	* 页面信息
//	****************************/
	/** 表格页面ID */
	protected String pageID;
	/** 系统路径 */
	protected String sHomeUrl;
	/** 用户信息 */
	protected UserInfo mUser;
	/** 封装表格对象和分页组件的DIV页面ID */
	protected String outerContainerId;
	/** 需要绑定的数据集 */
	protected OperatorResult rs;

	/** 存储是否显示列重复数据 */
	protected ArrayList<String> hiddenRepeatData;
	/** 存储列内容,列名为键,用于需要剔重显示列 */
	protected KvMap<String, String> colContent;
	/** 列是否显示 */
	protected ArrayList<Boolean> preShow;
	/** 每列对应数据集的列名 */
	protected ArrayList<String>  colFieldName;

//	/***********************
//	* 分页信息
//	***********************/
	/** 分页动作ID */
	protected String pageActID; 
	/** 分页更新对象ID */
	protected String targID;
	/** 分页附加参数容器 */
	protected KvMap<String, String> pageAddParamContainer;
	/** 当前表格记录ID */
	protected String recordId ;
	/** 分页模版对象 */
	protected PagingComp pageComp = null; 
	/** 数据集分页信息 */
	protected Paging pageInfo = null;
	/** 分页附加参数容器ID */
	protected static final String Page_Add_Param_Container = ".pageAddParamCId";

	public DimTable(String sHomeUrl,UserInfo mUser,String pageID,OperatorResult rs){

		this.sHomeUrl = sHomeUrl;
		this.mUser = mUser;
		this.pageID = pageID;
		this.rs = rs;

		this.outerContainerId = pageID+".outc";
		this.hiddenRepeatData = new ArrayList<String>();
		this.colContent = new KvMap<String, String>();
	}

	/**
	 *  设置需要剔重列,可以设置多个或者多次设置
	 * @param sColFieldName 列名(按照列的先后顺序设置)
	 */
	public void setRemoveRepeatCol(String... sColFieldNames) throws ErrorMessage{
		if(this.hiddenRepeatData == null)
			this.hiddenRepeatData = new ArrayList<String>();
		for(String fieldName:sColFieldNames){
			this.hiddenRepeatData.add(fieldName);
		}
	}

	/**
	 * 设置表格分页参数(要刷新的目标区域ID就是当前表格)
	 * @param pageActID  分页跳转动作ID
	 * @param recordId   分页页面记录ID
	 */
	public void setPageProperty(String pageActID, String recordId){
		this.setPageProperty(pageActID, recordId,null);
	}

	/**
	 * 设置表格分页参数(要刷新的目标区域不是当前表格)
	 * @param pageActID  分页跳转动作ID
	 * @param recordId   分页页面记录ID
	 * @param targID     要刷新的目标区域ID
	 */
	public void setPageProperty(String pageActID, String recordId, String targID){
		this.pageActID = pageActID;
		this.recordId = recordId;
		this.targID = targID;
	}

	/**
	 *  放入分页所需附加参数
	 * @param paramName 参数名称
	 * @param paramValue 参数值
	 * @throws ErrorMessage 
	 */
	public void putPageAddParam(String paramName, String paramValue) throws ErrorMessage{
		if(this.pageAddParamContainer==null)
			this.pageAddParamContainer = new KvMap<String, String>();
		this.pageAddParamContainer.put(paramName, paramValue);
	}

	/**
	 * 设置分页属性
	 * @throws ErrorMessage 
	 */
	protected HtmlWindow getPageProperty(OperatorResult rs,
			String outerContainerId,
			String pageID,
			int tableWidth,
			Table table) throws ErrorMessage{
		HtmlWindow page = null;
		if(rs!=null){
			this.pageInfo = rs.getPaging();
		}
		if(pageInfo!=null && pageInfo.getTotal()>1){
			if(pageActID==null)throw new ErrorMessage("Page Componet Action ID have not been set at RfFlowTable!");
			if(this.targID==null)this.targID = outerContainerId;//如果为设置目标刷新区域当前表格为目标刷新区域
			//创建分页组件
			pageComp = new PagingComp(pageID,this.pageActID,this.targID);
			//设置宽度
			if(tableWidth>0){
				pageComp.setWidth(tableWidth);
			}
			//设置分页附加参数
			setPageAddParams(pageID,table);
			//获取分页组件
			page = pageComp.get(this.mUser, 
					this.sHomeUrl, this.pageInfo,this.recordId);
		}
		return page;
	}

	/**
	 *  设置分页附加参数
	 * @throws ErrorMessage 
	 */
	protected void setPageAddParams(String pageID,Table table) throws ErrorMessage{
		if(this.pageAddParamContainer==null
				|| this.pageAddParamContainer.size()<1) return;
		String addPId = pageID+Page_Add_Param_Container;
		HiddenParams addParams = new HiddenParams(addPId);
		for(Map.Entry<String, String> s: this.pageAddParamContainer){
			addParams.put(s.getKey(), s.getValue());
		}
		pageComp.setAddParamsCId(addParams.getID());//放入附加参数容器
		table.putExtend(addParams.get());//放入附加参数到表格
	}

	/**
	 *  获取需要剔除重复列的当前单元格是否显示<BR>
	 *  如果不需要替重,直接返回true
	 *  需要剔重:当前列内容和上一列相同返回false,否则返回true
	 */
	protected boolean showContent(Result result,
			String fieldName,
			KvMap<String, String> colContent,
			int colIndex) throws ErrorMessage{
		if(this.preShow==null)repeatCol();
		boolean displayRepeat = 
			this.hiddenRepeatData.contains(fieldName);
		if(!displayRepeat){//当前单元格不需要剔重
			return true;
		}
		//获取当前列内容
		String content = result.getString(fieldName);
		//如果上一列显示则当前列也显示
		int curIndex = this.hiddenRepeatData.indexOf(fieldName);//当前剔重行排序号
		if(curIndex>0 && 
				this.preShow.get(curIndex-1)){
			this.preShow.set(curIndex, true);
			if(content!=null)colContent.put(fieldName, content);
			return true;
		}
		String preColContent = colContent.getByKey(fieldName);//获取列旧内容
		//如果当前列内容第一次设置,设置显示当前单元格
		if(!colContent.containsKey(fieldName)
				&& content!=null){
			colContent.put(fieldName, content);
			this.preShow.set(curIndex, true);
			return true;
		}
		//比较当前列内容与旧内容
		if((preColContent==null && content==null)
				||(preColContent!=null && preColContent.equals(content))
		){//当前单元格内容与上一行相同,设置不显示当前单元格
			this.preShow.set(curIndex, false);
			return false;
		}else{//设置列比较器的内容为当前列内容,设置显示当前单元格
			colContent.put(fieldName, content);
			this.preShow.set(curIndex, true);
			return true;
		}
	}

	/**
	 * @param fieldName 字段名称
	 * @return 是否维度字段
	 */
	protected boolean isDim(String fieldName){
		if(this.hiddenRepeatData==null)return false;
		return this.hiddenRepeatData.contains(fieldName);
	}

	/**
	 *  设置剔除重复列
	 * @throws ErrorMessage 
	 */
	protected void repeatCol() throws ErrorMessage{
		ArrayList<String> hidden = new ArrayList<String>();
		if(this.preShow == null)
			this.preShow = new ArrayList<Boolean>();
		String fieldName;
		for(int i=0;i<this.colFieldName.size();i++){
			fieldName = colFieldName.get(i);
			if(this.hiddenRepeatData.contains(fieldName)){
				hidden.add(fieldName);
				this.preShow.add(false);
			}
		}
		this.hiddenRepeatData = hidden;
	}

	/**
	 *  创建单元格内容
	 * @param callback       列内容回调器
	 * @param actionCallback 列动作回调器
	 * @param rowIndex       列容器ID
	 * @return 单元格内容
	 * @throws ErrorMessage
	 */
	protected HtmlWindow createCol(String sHomeUrl,
			UserInfo mUser,
			CallBack callback,
			ActionCallback actionCallback,
			String rowIndex,
			String recordId,
			Result result,
			int colIndex,
			String fieldName) throws ErrorMessage{
		//获取是否显示单元格
		boolean showContent = this.showContent(result, fieldName, this.colContent, colIndex);
		//创建单元格内容
		HtmlWindow win = null;
		if(callback!=null && showContent){
			win = callback.getGroup(result, sHomeUrl, mUser)[0];//回调器第一个元素为单元格内容
		}else{
			win = new HtmlDiv();
		}
		//创建单元格
		Cell cell= null;
		if(showContent && this.isDim(fieldName)){
			cell = new DimensionCell();//维度单元格
		}else{
			cell = new EmptyCell();//非维度单元格
		}
		cell.put(win);
		HtmlWindow div = cell.get();
		//绑定单元格事件
		if(actionCallback!=null && callback!=null&& showContent){
			div.bind(Window_Event.OnClick,
					getActionScript(actionCallback, rowIndex, recordId, result));
		}
		return div;
	}

	/**
	 *  根据脚本回调器生成脚本
	 */
	private String getActionScript(ActionCallback actionCallback,
			String rowIndex,
			String recordId,
			Result result
	) throws ErrorMessage{
		if(actionCallback==null)return null;
		String script = null;
		if(!actionCallback.isCustomerModel()){
			actionCallback.process(result);//获取自定义提交动作
			script = TableScript.getBindScript(
					actionCallback,//绑定动作回调器
					rowIndex,   //提交容器为当前行
					recordId);  //附加参数
		}else{
			script = actionCallback.getCustomerScript(result, recordId);
		}
		return script;
	}
}
